﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ForguncyPluginCreator
{
    internal class PluginProjectCreator
    {
        public static void Create(string templateFolder, string targetFolder, MainWindow.MainWindowViewModel settings, string forguncyVersion)
        {
            templateFolder = Path.GetFullPath(templateFolder);
            targetFolder = Path.GetFullPath(targetFolder);
            var files = Directory.GetFiles(templateFolder, "*.*", SearchOption.AllDirectories);
            var officalPlugin = settings.OfficalPlugin;
            foreach (var item in files)
            {
                var relativePath = item.Substring(templateFolder.Length + 1);
                var targetRelativePath = GetReplacedStr(relativePath, settings, forguncyVersion, officalPlugin);
                var targetPath = Path.Combine(targetFolder, targetRelativePath);
                var extension = Path.GetExtension(item).ToLower();

                if (NeedSkip(item, settings, officalPlugin))
                {
                    continue;
                }
                EnsureFolder(targetPath);
                var textExtentions = new string[] { "cs", "js", "css", "map", "ts", "sln", "csproj", "json", "xaml" };
                if (textExtentions.Any(i => extension == "." + i))
                {
                    var sourceContent = File.ReadAllText(item);

                    if (settings.UseJavaScript)
                    {
                        if (item.EndsWith("ForguncyPluginTemplateCellType.js") || item.EndsWith("ForguncyPluginTemplateCommand.js"))
                        {
                            sourceContent = "/// <reference path=\"../Declarations/forguncy.d.ts\" />\r\n/// <reference path=\"../Declarations/forguncy.Plugin.d.ts\" />\r\n\r\n" + sourceContent;

                            sourceContent = sourceContent.Replace("\r\n//# sourceMappingURL=ForguncyPluginTemplateCommand.js.map", "")
                                .Replace("\r\n//# sourceMappingURL=ForguncyPluginTemplateCellType.js.map", "");
                        }
                        if (item.EndsWith("ForguncyPluginTemplate.csproj"))
                        {
                            sourceContent = sourceContent.Replace("\r\n\t\t<None Remove=\"Resources\\*.js\" />", "")
                                .Replace("\r\n\t\t<None Remove=\"Resources\\*.js.map\" />", "");
                        }
                    }

                    if (Path.GetFileName(item) == "PluginConfig.json")
                    {
                        sourceContent = UpdatePluginConfigContentByPluginType(sourceContent, settings);
                    }
                    if (Path.GetExtension(item) == ".csproj")
                    {
                        sourceContent = UpdateTemplateCsProject(sourceContent, settings);
                    }

                    var content = GetReplacedStr(sourceContent, settings, forguncyVersion, officalPlugin);
                    File.WriteAllText(targetPath, content);
                }
                else
                {
                    File.Copy(item, targetPath);
                }
            }
            if (!officalPlugin)
            {
                CopyPluginPackageTool(targetFolder);
            }
        }

        private static void CopyPluginPackageTool(string targetFolder)
        {
            var packageTool = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            var targetPackToolFolder = Path.Combine(targetFolder, "PackageTools");
            var files = new string[]
            {
                "ForguncyPluginPackageTool.exe",
                "ForguncyPluginPackageTool.dll",
                "ForguncyPluginPackageTool.deps.json",
                "ForguncyPluginPackageTool.runtimeconfig.json",
                "Newtonsoft.Json.dll",
                "PluginAnalyzer.dll",
                "PluginAnalyzer.deps.json"
            };
            if (!Directory.Exists(targetPackToolFolder))
            {
                Directory.CreateDirectory(targetPackToolFolder);
            }
            foreach (var file in files)
            {
                var source = Path.Combine(packageTool, file);
                if (File.Exists(source))
                {
                    File.Copy(source, Path.Combine(targetPackToolFolder, file));
                }
            }
        }

        private static string UpdatePluginConfigContentByPluginType(string sourceContent, MainWindow.MainWindowViewModel settings)
        {
            if (!settings.ContainCellType && !settings.ContainCommand)
            {
                sourceContent = sourceContent.Replace("    \"Resources/ForguncyPluginTemplateCellType.js\",\r\n    \"Resources/ForguncyPluginTemplateCommand.js\"", "");
            }
            if (!settings.ContainCellType)
            {
                sourceContent = sourceContent.Replace("    \"Resources/ForguncyPluginTemplateCellType.js\",\r\n    \"Resources/ForguncyPluginTemplateCommand.js\"", "    \"Resources/ForguncyPluginTemplateCommand.js\"");
                sourceContent = sourceContent.Replace("\"pluginType\": \"cellType,command\",", "\"pluginType\": \"command\",");
            }
            if (!settings.ContainCommand)
            {
                sourceContent = sourceContent.Replace("    \"Resources/ForguncyPluginTemplateCellType.js\",\r\n    \"Resources/ForguncyPluginTemplateCommand.js\"", "    \"Resources/ForguncyPluginTemplateCellType.js\"");
            }
            if (!settings.ContainServerCommand && !settings.ContainCommand)
            {
                sourceContent = sourceContent.Replace("\"pluginType\": \"cellType,command\",", "\"pluginType\": \"cellType\",");
            }
            return sourceContent;
        }

        private static string UpdateTemplateCsProject(string sourceContent, MainWindow.MainWindowViewModel settings)
        {
            var newlines = new List<string>();
            var lines = sourceContent.Split("\r\n");
            var skipKey = settings.OfficalPlugin ? "<ItemGroup Label=\"DLLReferrenct\">" : "<ItemGroup Label=\"ProjectReferrenct\">";
            var keepKey = !settings.OfficalPlugin ? "<ItemGroup Label=\"DLLReferrenct\">" : "<ItemGroup Label=\"ProjectReferrenct\">";
            var skip = false;
            foreach (var curline in lines)
            {
                var line = curline;
                if (skip)
                {
                    if (line.Contains("</ItemGroup>"))
                    {
                        skip = false;
                    }
                    continue;
                }
                if (line.Contains(skipKey))
                {
                    skip = true;
                    continue;
                }
                if (line.Contains(keepKey))
                {
                    line = line.Replace(keepKey, "<ItemGroup>");
                }
                newlines.Add(line);
            }
            return string.Join("\r\n", newlines);
        }

        private static bool NeedSkip(string item, MainWindow.MainWindowViewModel settings, bool officalPlugin)
        {
            if (officalPlugin)
            {
                // 非官方插件默认不包含.d.ts
                if (item.EndsWith(".d.ts"))
                {
                    return true;
                }
            }
            else
            {
                // 非官方插件默认不包含多语言支持
                if (item.EndsWith("Resources.Designer.cs") ||
                    item.EndsWith("ResourceAttributes.cs") ||
                    item.EndsWith(".resx"))
                {
                    return true;
                }
            }

            // 如果是JavaScript，跳过Ts部分
            if (settings.UseJavaScript)
            {
                if (item.EndsWith(".js.map") || item.EndsWith("tsconfig.json"))
                {
                    return true;
                }
                if (item.EndsWith(".ts") && !item.EndsWith(".d.ts"))
                {
                    return true;
                }
            }

            if (item.Contains(@".vs\") || item.Contains(".user") || item.Contains(@"bin\") || item.Contains(@"obj\"))
            {
                return true;
            }
            var fileName = Path.GetFileName(item);
            if (!settings.ContainCellType)
            {
                if (fileName.Contains("ForguncyPluginTemplateCellType"))
                {
                    return true;
                }
            }
            if (!settings.ContainCommand)
            {
                if (fileName.Contains("ForguncyPluginTemplateCommand"))
                {
                    return true;
                }
            }
            if (!settings.ContainServerCommand)
            {
                if (fileName.Contains("ForguncyPluginTemplateServerCommand"))
                {
                    return true;
                }
            }
            if (!settings.ContainCellType && !settings.ContainCommand)
            {
                if (fileName.Contains(".d.ts"))
                {
                    return true;
                }
            }
            return false;
        }

        public static void EnsureFolder(string file)
        {
            var path = Path.GetDirectoryName(file);
            if (string.IsNullOrEmpty(path))
            {
                return;
            }

            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }
        }
        public static string GetReplacedStr(string str, MainWindow.MainWindowViewModel settings, string forguncyVersion, bool officalPlugin)
        {
            var forguncyFolder = settings.ForguncyInstallPath;
            var packageToolPath = "..\\PackageTools\\ForguncyPluginPackageTool.exe";
            var analyzerPath = "..\\PackageTools\\PluginAnalyzer.dll";

            var forguncyWebsitePath = settings.ForguncyWebsitePath;
            var forguncyInstallPath = settings.ForguncyInstallPath;
            if (officalPlugin)
            {
                var pluginFolder = Path.Combine(settings.PluginPath, settings.Name);
                forguncyWebsitePath = Path.GetRelativePath(pluginFolder, settings.ForguncyWebsitePath);
                forguncyInstallPath = Path.GetRelativePath(pluginFolder, settings.ForguncyInstallPath);

                var pluginRoot = Path.Combine(settings.ForguncyInstallPath, "Plugin");
                var pluginRelativeFolder = Path.GetRelativePath(settings.PluginPath, pluginRoot);

                str = str.Replace("%PluginFolder%", pluginRelativeFolder + @"\..");

                analyzerPath = Path.Combine(Path.GetRelativePath(pluginFolder, pluginRoot), "PackageTools", "PluginAnalyzer.dll");
                packageToolPath = Path.Combine(Path.GetRelativePath(pluginFolder, pluginRoot), "PackageTools", "ForguncyPluginPackageTool.exe");

                str = str.Replace("Declarations/forguncy.d.ts", Path.Combine(forguncyInstallPath, @"Forguncy.Declaration\src\forguncy.d.ts").Replace("\\", "/"))
                    .Replace("Declarations/forguncy.Plugin.d.ts", Path.Combine(forguncyInstallPath, @"Forguncy.Declaration\src\forguncy.Plugin.d.ts").Replace("\\", "/"));

                str = str.Replace(@"""executablePath"": ""C:\\Program Files\\Forguncy 8\\Website\\designerBin\\Forguncy.exe""", @"""executablePath"": ""..\\" + forguncyWebsitePath.Replace(@"\", @"\\") + @"\\designerBin\\Forguncy.exe""");
            }

            return str
                .Replace("C:\\Program Files\\Forguncy 8\\Website", forguncyWebsitePath.TrimEnd('\\'))
                .Replace("C:\\\\Program Files\\\\Forguncy 8\\\\Website", forguncyWebsitePath.TrimEnd('\\').Replace("\\", "\\\\"))
                .Replace("C:\\Program Files\\Forguncy 8", forguncyInstallPath.TrimEnd('\\'))
                .Replace("C:\\\\Program Files\\\\Forguncy 8", forguncyInstallPath.TrimEnd('\\').Replace("\\", "\\\\"))
                .Replace("%PackageToolPath%", packageToolPath)
                .Replace("%AnalyzerPath%", analyzerPath)
                .Replace("%ForguncyInstallPath%", forguncyFolder)
                .Replace("ForguncyPluginTemplate-LacaleName", settings.LocaleName ?? settings.Name)
                .Replace("ForguncyPluginTemplate-GUID", Guid.NewGuid().ToString())
                .Replace("ForguncyPluginTemplate-Description", settings.Description)
                .Replace("ForguncyPluginTemplate-DependenceVersion-Version", forguncyVersion)
                .Replace("ForguncyPluginTemplate", settings.Name);
        }
    }
}
